package app.service;

import app.entity.Pager;
import app.entity.UserInfo;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import siotwx.dao.*;
import siotwx.entity.*;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 这个类用于管理设施处理的业务逻辑
 * @author 昊琦
 *创建时间2018年3月9日14:40:01
 * @author 周超 修改 2018年3月13日
 */
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT)
@Service("FacilitiesManageService")
public class FacilitiesManageService {

	@Autowired
	@Qualifier("FacdevDao")
	private FacdevDao facdevDao;
	
	@Autowired
	@Qualifier("FacilitiesDao")
	private FacilitiesDao facDao;
	
	@Autowired
	@Qualifier("FacmonitoringDao")
	private FacmonitoringDao facmonitoringDao;
	
	@Autowired
	@Qualifier("FaultnumDao")
	private FaultnumDao faultnumDao;
	
	@Autowired
	@Qualifier("OperatorviewDao")
	private OperatorviewDao OperDao;
	
	@Autowired
	@Qualifier("DeviceDao")
	private DeviceDao devDao;
	
	@Autowired
	@Qualifier("UserDao")
	private UserDao userDao;
	
	@Autowired
	@Qualifier("EventlogDao")
	private EventlogDao eventDao;
	
	@Autowired
	@Qualifier("AlllogDao")
	private AlllogDao logDao;
	/**
	 * 获取该地区未绑定的设施总数
	 * @param regionId
	 * @return
	 */
	@Transactional(readOnly = true)
	public int countAllFacNotBind(int regionId){
		
		Map<String, Object> params =new HashMap<>();
		
		params.put("regionId", regionId);
		params.put("devCode", "");
		int count = facdevDao.count(params);
		
		
		return count;
	}
	
	/**
	 * 获取该地区的设施总数
	 * @param regionId
	 * @return
	 */
	@Transactional(readOnly = true)
	public int countAllFac(int regionId){
		
		Map<String, Object> params =new HashMap<>();
		
		params.put("regionId", regionId);
		int count = facdevDao.count(params);
		
		
		return count;
	}
	

	
	/**
	 * 统计各个设施的分组以及数量
	 * @param regionId
	 * @return
	 */
	@Transactional(readOnly=true)
	public List<HashMap<String, Object>> countFacGroupNum(int regionId){
		
		return facDao.countFacGroupNum(regionId);
	}
	
	/**
	 * 获取设施告警记录的文本
	 * @param regionId
	 * @return
	 */
	@Transactional(readOnly=true)
	public List<HashMap<String, Object>> getWarningText(int regionId){
		return facmonitoringDao.getWarningText(regionId);
		
	}
	
	/**
	 * 根据regionId统计该地区的告警状态设施数量
	 * @param regionId
	 * @return
	 */
	@Transactional(readOnly=true)
	public int countFacFaultnum(int regionId){
		
		Map<String, Object> params = new HashMap<>();
		params.put("regionId", regionId);
		return faultnumDao.count(params);
	}
	
	/**
	 * 获取一次设施的实时状态
	 * @param sql
	 * @param param
	 * @return
	 */
	@Transactional(readOnly=true)
	public List<Facmonitoring> monitorFac(String sql,Map<String,Object> param){
		
		return facmonitoringDao.getListBySql(sql, param);
	} 
	
	
	/**
	 * 根据设施上的设备的id获取最新的设施的实时状态
	 * @param devIds
	 * @return
	 */
	@Transactional(readOnly=true)
	public List<Facmonitoring> updateFacStu(List<String> devIDs){
		List<Facmonitoring> listByIn = facmonitoringDao.getListByIn("devId",devIDs);
		//获取在线设备
		List<String> deviceOnline = deviceOnline();
		//设置在线设备状态
		changeSate(listByIn,deviceOnline);
		
		
		return listByIn;
	}
	
	private void changeSate(List<Facmonitoring> listByIn, List<String> deviceOnline) {
		int len=listByIn!=null?listByIn.size():0;
		List<Facmonitoring> res=new ArrayList<>();
		for(int i=0;i<len;i++) {
			Facmonitoring facmonitoring = listByIn.get(i);
			if (facmonitoring.getDevCode()!=null&&facmonitoring.getDevCode().startsWith("D")) {
				facmonitoring.setEventDevstu("0");
			}
			for(String code:deviceOnline) {
				if (code.equals(facmonitoring.getDevCode())) {
					facmonitoring.setEventDevstu("1");
				}
			}
			res.add(facmonitoring);
		}
		listByIn=res;
	}

	/**
	 * @author 周超 添加 2018年3月13日 
	 */
	
	/**
	 * 用于获取指定区域，指定设施的可以开门的人员列表
	 * 
	 * @param region 地区id
	 * @param facID 设施的id
	 * @return 能够开锁的用户信息列表
	 */
	@Transactional(readOnly=true)
	public List<UserInfo> usersCanOpenTheDoorG(Integer region,Integer facID){
		//获取该设施关联的所有设备
		List<Device> devices = devDao.getlist(new HashMap<String,Object>(){{
			put(Device.FieldName.facilities_id.toString(), facID);
		}});
		//保存全部可以开锁的用户
		List<UserInfo> res=new ArrayList<>();
		//从关联设备中获取所有的机柜设备
		DateFormat format=new SimpleDateFormat("yyyy/MM/dd HH:mm");
		List<Device> devs=new ArrayList<>();
		if (devices!=null&&devices.size()!=0) {
			for (Device device : devices) {
				if (device.getCode().startsWith("L")) {
					devs.add(device);
				}
			}
			for(Device device:devs){
				Map<String, Object> params=new HashMap<>();
				params.put(Operatorview.FieldName.devId.toString(), device.getId());
				List<Operatorview> Operatorlist = OperDao.getlist(params);
				
				for (Operatorview operatorview:Operatorlist) {
					if (System.currentTimeMillis() > operatorview.getEventEnd()) {
						User user = userDao.get(operatorview.getDevId());
						if (user!=null&&user.getRegion_id().equals(region)) {
							UserInfo userInfo = new UserInfo(user.getId(), user.getPhoneNumber(),
									format.format(new Date(operatorview.getEventEnd())), user.getRealName());
							res.add(userInfo);
						}
					} 
				}
			}
		}
		Facilities facilities = facDao.get(facID);
		if (facilities!=null&&facilities.getUser_id()!=0) {
			User user = userDao.get(facilities.getUser_id());
			UserInfo userInfo=new UserInfo(user.getId(), user.getPhoneNumber(), "永久", user.getRealName());
			res.add(userInfo);
		}
		
		return res;
	}
	/**
	 * 该方法用来确认指定用户是否可以打开指定的锁
	 * 
	 * @param userID 用户id
	 * @param region 区域id
	 * @param facID 设施id
	 * @return 返回true则可以打开锁
	 */
	@Transactional(readOnly=true)
	public boolean canOpenTheDoorG(Integer userID,Integer region,Integer facID){
		List<UserInfo> usersCanOpenTheDoorG = usersCanOpenTheDoorG(region, facID);
		for(UserInfo userInfo:usersCanOpenTheDoorG){
			if (userInfo.getId().intValue()==userID.intValue()) {
				return true;
			}
		}
		
		return false;
	}
	/**
	 * 用于获取指定区域，指定设施的可以开门的人员列表
	 * 
	 * @param region 地区id
	 * @param facID 设施的id
	 * @return 能够开锁的用户信息列表
	 */
	@Transactional(readOnly=true)
	public List<UserInfo> usersCanOpenTheDoorF(Integer region,Integer facID){
		//获取该设施关联的所有设备
		List<Device> devices = devDao.getlist(new HashMap<String,Object>(){{
			put(Device.FieldName.facilities_id.toString(), facID);
		}});
		//保存全部可以开锁的用户
		List<UserInfo> res=new ArrayList<>();
		//从关联设备中获取所有的机柜设备
		DateFormat format=new SimpleDateFormat("yyyy/MM/dd HH:mm");
		List<Device> devs=new ArrayList<>();
		if (devices!=null&&devices.size()!=0) {
			for (Device device : devices) {
				if (device.getCode().startsWith("D")) {
					devs.add(device);
				}
			}
			for(Device device:devs){Map<String, Object> params=new HashMap<>();
			params.put(Operatorview.FieldName.devId.toString(), device.getId());
			List<Operatorview> Operatorlist = OperDao.getlist(params);
			
			for (Operatorview operatorview:Operatorlist) {
				if (System.currentTimeMillis() < operatorview.getEventEnd()) {
					User user = userDao.get(operatorview.getDevId());
					if (user!=null&&user.getRegion_id().equals(region)) {
						UserInfo userInfo = new UserInfo(user.getId(), user.getPhoneNumber(),
								format.format(new Date(operatorview.getEventEnd())), user.getRealName());
						res.add(userInfo);
					}
				} 
			}}
		}
		Facilities facilities = facDao.get(facID);
		if (facilities!=null&&facilities.getUser_id()!=0) {
			User user = userDao.get(facilities.getUser_id());
			UserInfo userInfo=new UserInfo(user.getId(), user.getPhoneNumber(), "永久", user.getRealName());
			res.add(userInfo);
		}
		
		return res;
	}
	/**
	 * 该方法用来确认指定用户是否可以打开指定的锁
	 * 
	 * @param userID 用户id
	 * @param region 区域id
	 * @param facID 设施id
	 * @return 返回true则可以打开锁
	 */
	@Transactional(readOnly=true)
	public boolean canOpenTheDoorF(Integer userID,Integer region,Integer facID){
		List<UserInfo> usersCanOpenTheDoorG = usersCanOpenTheDoorF(region, facID);
		for(UserInfo userInfo:usersCanOpenTheDoorG){
			if (userInfo.getId().intValue()==userID.intValue()) {
				return true;
			}
		}
		return false;
	}

	
	/**
	 * 该方法用来返回指定地区绑定的或者没有绑定的设施的信息
	 * @author 周超 2018年3月14日 
	 * 
	 * @param region 地区id
	 * @param is_bind 是否绑定bool型
	 * @param pageNum 页码
	 * @return
	 */
	@Transactional(readOnly=true)
	public List<Facdev> facdevInfo(Integer region,boolean is_bind,Integer pageNum){
		if (is_bind) {
			//获取全部该地区的设施情况
			Map<String, Object> params = new HashMap<>();
			params.put(Facdev.FieldName.regionId.toString(), region);
			List<Facdev> facList = facdevDao.getlist(params);
			//获取全部绑定了的设施
			List<Facdev> facBindList=new ArrayList<>();
			for(Facdev facdev:facList){
				if (!"".equals(facdev.getDevCode())) {
					facBindList.add(facdev);
				}
			}
			//进行分页处理
			Pager pager=new Pager(facBindList.size(), pageNum);
			List<Facdev> facBindPager=new ArrayList<>();
			for(int index=(pager.getPagenumber()-1)*pager.getPagesize();
					index<(pager.getPagenumber()-1)*pager.getPagesize();
					index++){
				facBindPager.add(facBindList.get(index));
			}
			
			return facBindPager;
			
		}else {
			Map<String, Object> params = new HashMap<>();
			params.put(Facdev.FieldName.regionId.toString(), region);
			params.put(Facdev.FieldName.devCode.toString(), "");
			Pager pager=new Pager(facdevDao.count(params), pageNum);
			params.put("pager", pager);
			List<Facdev> list = facdevDao.getlist(params);
			return list;
		}
	}

	/**
	 * 获取某个地区某种设施 上的所有故障设备
	 * @author 昊琦
	 * @param modType
	 * @param regionId
	 * @创建时间：2018年3月15日16:30:04
	 * @return
	 */
	@Transactional(readOnly=true)
	public List<Facmonitoring>  getFacWarningData(String modType,int regionId){
		
		String sql = "select *  from facmonitoring where devCode like '"+modType+"%' and (eventDevstu ='0' or eventDoorstu='0') "
				+ " and facRegionId = "+regionId;
		
		return facmonitoringDao.getListBySql(sql, null);
		
	}
	
	/**
	 * 获取某个地区所有的绑定的且正常工作过的设施和设施绑定的设备
	 * @author 昊琦
	 * @param regionId
	 * @创建时间 2018年3月15日16:30:28
	 * @return
	 */
	@Transactional(readOnly=true)
	public List<Facmonitoring> getFacmonitoring(int regionId){
		
		Map<String, Object> params = new HashMap<>();
		params.put("facRegionId", regionId);
		
		return facmonitoringDao.getlist(params);
		
	}
	/**
	 * @author 周超 2018年3月16日 
	 */
	//处理用来获取全部设施的绑定情况
	@Transactional(readOnly=true)
	public List<Facdev> facdevMap(String sql,Pager pager){
		Map<String, Object> params=new HashMap<>();
		List<Facdev> getlist = facdevDao.getlistBySql(sql, pager);
		return getlist;
	}
	
	/**
	 * 根据设备code查询它被绑定的设施的实时监控状态信息
	 * @author 昊琦
	 * @param regionId
	 * @创建时间 2018年3月15日16:30:28
	 * @return
	 */
	@Transactional(readOnly=true)
	public Facmonitoring getFacmonitoring(String devCode){
		
		Map<String, Object> params = new HashMap<>();
		params.put("devCode", devCode);
		List<Facmonitoring> list = facmonitoringDao.getlist(params);
		
		if (list!=null&&!list.isEmpty()) {
			return list.get(0);
		}else{
			return null;
		}
	}
	
	@Transactional(readOnly=true)
	public List<Alllog> getAllLogs(String sql,Pager pager){
		return logDao.getAllLogBySql(sql,pager);
	}
	
	/**
	 * 更新设备状态，门状态和电量信息
	 * @param eventlog
	 * @param devStu
	 * @param doorStu
	 * @param electricity
	 */
	@Transactional(readOnly=false)
	public void updateDevstuDoorstuElectricity(Eventlog eventlog,String devStu,String doorStu,String electricity){
		
		
		eventlog.setDevStu(devStu);
		eventlog.setDoorStu(doorStu);
		eventlog.setElectricity(electricity);
		
		eventDao.update(eventlog);
	}
	
	/**
	 * 根据设施id查询设施的详细信息
	 * @param facId 设施id
	 * @return
	 */
	@Transactional(readOnly=true)
	public Facilities get(int facId){
		return facDao.get(facId);
	}
	
	/**
	 * 根据事件ID获取设施的事件
	 * @param eventId
	 * @return
	 */
	@Transactional(readOnly=true)
	public Eventlog getEvent(int eventId){
		return eventDao.get(eventId);
	}
	//获取在线设备
	private List<String> deviceOnline(){
		List<String> res=new ArrayList<>();
		try {
			URL url=new URL("https://www.3firelink.com/AcceptTransmitServer/LockCondition");
			HttpURLConnection connection = (HttpURLConnection) url.openConnection();
			connection.setRequestMethod("POST");
			connection.setRequestProperty("token_key", "aqscxkz");
			InputStream stream = connection.getInputStream();
			int len=0;
			byte[] buff=new byte[20];
			StringBuilder builder=new StringBuilder();
			while((len=stream.read(buff))>0) {
				builder.append(new String(buff, 0,len));
			}
			//{"devCodes":[]}
			JsonParser parser=new JsonParser();
			JsonArray devs = parser.parse(builder.toString()).getAsJsonObject().get("devCodes").getAsJsonArray();
			for(JsonElement JE:devs) {
				String devCode = JE.getAsString();
				res.add(devCode);
			}
			
			
		} catch (Exception e) {
			e.printStackTrace();
		}finally {

			return res;
		}
		
		
	}

}
